namespace SubhadraSolutions.Sharp.Logging.Context
{
    using SubhadraSolutions.Sharp.Logging.Contracts;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Threading;

    public sealed class ThreadDictionaryGlobalContextStrategy : IClearableGlobalContextStrategy
    {
        #region Fields

        private readonly ConcurrentDictionary<int, Dictionary<string, object>> _dictionary =
            new ConcurrentDictionary<int, Dictionary<string, object>>();

        #endregion Fields

        #region Indexers

        public object this[string name]
        {
            get
            {
                if (name != null)
                {
                    Dictionary<string, object> d;
                    if (_dictionary.TryGetValue(Thread.CurrentThread.ManagedThreadId, out d))
                    {
                        object o;
                        d.TryGetValue(name, out o);
                        return o;
                    }
                }
                return null;
            }
            set
            {
                if (name != null)
                {
                    if (value == null)
                    {
                        Remove(name);
                    }
                    else
                    {
                        Dictionary<string, object> d =
                            _dictionary.GetOrAdd(Thread.CurrentThread.ManagedThreadId,
                                key => (new Dictionary<string, object>()));
                        d[name] = value;
                    }
                }
            }
        }

        #endregion Indexers

        #region Methods

        public void Clear()
        {
            Dictionary<string, object> d;
            _dictionary.TryRemove(Thread.CurrentThread.ManagedThreadId, out d);
        }

        public void Remove(string name)
        {
            if (name != null)
            {
                Dictionary<string, object> d;
                if (_dictionary.TryGetValue(Thread.CurrentThread.ManagedThreadId, out d))
                {
                    d.Remove(name);
                }
            }
        }

        #endregion Methods
    }
}